<?php

namespace App\Http\Controllers\Accident;

use App\Http\Controllers\Controller;
use App\Models\Accident\Accident;
use App\Models\Accident\AccidentDocument;
use App\Models\Accident\AccidentInjured;
use App\Models\Accident\AccidentRepair;
use App\Models\Dict;
use App\Models\Personnel\Personnel;
use App\Models\Role;
use App\Models\Workflow\WorkflowLog;
use App\Models\Workflow\WorkflowNode;
use App\Models\Workflow\WorkflowNodeProgram;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\DB;

class AccidentController extends Controller
{
    public $groupId;

    public function __construct()
    {
        $userId = Auth::user()->id;
        $roleId = DB::table('sys_roles_users')->where('user_id', $userId)->pluck('role_id')->toArray();
        $this->groupId = $roleId;
    }
    public function accidentList(Request $request)
    {
        $params = $request->all();
        if ($params['date'][0] === null && $params['date'][1] === null) {
            $params['date'] = date('d') > 25 ?
                [
                    date('Y-m-26', strtotime('-1 month')),
                    date('Y-m-25'),
                ] :
                [
                    date('Y-m-26', strtotime('-2 month')),
                    date('Y-m-25', strtotime('-1 month')),
                ];
        } else {
            $date = $params['date'];
            $params['date'] = [
                date('Y-m-d', strtotime($date[0])),
                date('Y-m-d', strtotime($date[1])),
            ];
        }
        $data = $this->getAccidentList($params)->get()->toArray();
        $data = $this->transData($data);

        return response()->formatJson(['accidentRecord' => $data, 'date' => $params['date']]);
    }

    public function getAccidentList($params)
    {
        $query = Accident::with([
                'process' => function ($query) {
                    $query->where('apply_key', Accident::getTableName());
                }, 'process.node',
            ]);
        // $query=DB::table('akbus_accident as a')
        //     ->leftJoin('akbus_workflow_process as p', function ($join) {
        //         $join->on('a.id', '=', 'p.apply_id');
        //     })->leftJoin('akbus_bus_distribution as d', function ($join) {
        //         $join->on('a.license_plate_num', '=', 'd.license_plate_num')
        //             ->on(DB::raw('to_days(a.date)'), '>=', DB::raw('to_days(d.date)'))
        //             ->on(DB::raw('to_days(a.date)'), '<=', DB::raw('to_days(d.end_date)'));
        //     })
        //     ->select('a.*','p.node','d.line')
        //     ->where('p.apply_key',Accident::getTableName());

        if (isset($params['license_plate_num'])) {
            $query->where('license_plate_num', 'like', '%'.$params['license_plate_num'].'%');
        }
        if (isset($params['name'])) {
            $query->where('user_name', 'like', '%'.$params['name'].'%');
        }
        // if (isset($params['line'])) {
        //     $query->where('d.line', 'like', '%'.$params['line'].'%');
        // }

        return $query->whereBetween('date', [$params['date']])->orderByDesc('case_number');
    }

    /**
     * 数据转换
     *
     * @param  array  $data
     * @param  string  $type
     *
     * @return mixed
     */
    public function transData($data, $type = 'list')
    {
        $state = Dict::getOptionsArrByName('申请单状态');
        $personnel = Personnel::query()->where('type', 1)->pluck('name', 'id')->all();
        foreach ($data as $key => $apply) {
            // 用户id转化为用户姓名
            if (isset($apply['user_name'])) {
                // $data[$key]['driver'] = $type === 'list' ? $personnel[$apply['user_id']] : $apply['user_id'];
                $data[$key]['driver'] = $apply['user_name'];
            }

            // $group_id = Role::query()->where('id', Auth::user()->group_id)->value('name');

            $group_id = Role::query()->whereIn('id', $this->groupId)->pluck('name')->toArray();
            // 拼接审核状态，如：节点状态（操作人）
            if (isset($apply['process'])) {
                $status = $apply['process']['status'];
                if (($status === 1 || $status === 4) && in_array("事故-事故处理部",$group_id)) {
                    $data[$key]['editDisabled'] = false;
                    $data[$key]['editStyle'] = "color:#2d8cf0;font-size: 12px;";
                    $data[$key]['delDisabled'] = false;
                    $data[$key]['delStyle'] = "color:#2d8cf0;font-size: 12px;";
                } else {
                    $data[$key]['editDisabled'] = true;
                    $data[$key]['delDisabled'] = true;
                }
                $data[$key]['addStyle'] = "color:#2d8cf0;font-size: 12px;";
                $data[$key]['status'] = $status;
                $data[$key]['reason'] = $apply['process']['reason'];
                $node_name = $apply['process']['node'] ? '（'.$apply['process']['node']['node_name'].')' : '';
                $data[$key]['status_role'] = $state[$status].$node_name;
            }
            if (isset($apply['logs'])) {
                foreach ($apply['logs'] as $log) {
                    $data[$key]['auditRecord'][] = [
                        'nodeName'   => $log['node']['node_name'],
                        'resultName' => $log['result_name'],
                        'created_at' => $log['created_at'],
                        'reason'     => $log['reason'],
                        'number'     => $apply['number'],
                    ];
                }
            }
            if (! empty($apply['accident_file'])) {
                $images = explode(';', $apply['accident_file']);
                foreach ($images as $v) {
                    $data[$key]['images'][] = ['file_path' => $v];
                }
            }
        }

        return $data;
    }

    /**
     * 获取申请单数据到编辑表单页面
     *
     * @param $id
     *
     * @return mixed
     */
    public function edit($id)
    {
        $mrApply = Accident::with('injured')
            ->with('document')
            ->with([
                'process' => function ($query) {
                    $query->where('apply_key', Accident::getTableName());
                }, 'process.node',
            ])
            ->with([
                'logs' => function ($query) {
                    $query->where('apply_key', Accident::getTableName());
                }, 'logs.node',
            ])
            ->with('repair')
            ->find($id)
            ->toArray();
        $data = $this->transData([$mrApply], 'edit')[0];

        return response()->formatJson($data);
    }

    /**
     * 创建车辆信息
     *
     * @param  Request  $request
     *
     * @return mixed
     */
    public function storeAccident(Request $request)
    {
        $params = $request->all();

        // 删除陕G
        if ($params['license_plate_num']) {
            $params['license_plate_num'] = Str::of($params['license_plate_num'])->replace('陕G', '');
        }
        // UTC时间转化
        if ($params['date']) {
            $params['date'] = date('Y-m-d', strtotime($params['date']));
        }
        // 多文件转化为字符拼接
        if ($params['accident_file']) {
            $accidentFiles = array_column($params['accident_file'], 'file_path');
            $params['accident_file'] = implode(';', $accidentFiles);
        } else {
            $params['accident_file'] = '';
        }
        // 编制案号
        $params['number'] = $this->setAccidentNumber($params['date']);
        $params['user_name'] = $params['driver'];
        $accident = new Accident($params);
        $result = $accident->save();

        // 关联资料详情
        if (! empty($params['detailData'])) {
            foreach ($params['detailData'] as $work) {
                $work['type'] = 'file';
                $file = new AccidentDocument($work);
                $accident->document()->save($file);
            }
        }

        // 关联维修详情
        if (! empty($params['maintainData'])) {
            foreach ($params['maintainData'] as $pay) {
                $family = new AccidentRepair($pay);
                $accident->repair()->save($family);
            }
        }

        // 关联人伤情况
        if (! empty($params['hurtData'])) {
            foreach ($params['hurtData'] as $pay) {
                $family = new AccidentInjured($pay);
                $accident->injured()->save($family);
            }
        }

        $message = $result ? '添加成功' : '添加失败';

        $this->updateWorkflow($accident, $params['nodeKey'], $params['nodeType'], '');

        return response()->formatJson($result, $message);
    }


    /**
     * 设置申请单号
     * 单号规则：yyyymmdd+xxx(编号)，每天编号从001开始，且唯一
     * 如：20200101001
     *
     * @param $date
     *
     * @return string
     */
    public function setAccidentNumber($date): string
    {
        $accidentCount = Accident::withTrashed()->where('date', 'like', $date.'%')->count();

        return date('Ymd', strtotime($date)).sprintf("%03d", $accidentCount + 1);
    }

    /**
     * 更新工作流状态，写入审核状态日志
     *
     * @param $modelObj
     * @param $nodeKey
     * @param $nodeType
     * @param $reason
     */
    public function updateWorkflow($modelObj, $nodeKey, $nodeType, $reason): void
    {
        // 获取数据表名称
        $tableName = $modelObj->getTableName();

        // 1、查询节点
        $node = WorkflowNode::query()->firstWhere('node_key', $nodeKey);

        // 2、根据节点ID和节点类型，查询节点流转状态
        $nodeProgram = WorkflowNodeProgram::query()->where('node_id', $node->id)
            ->where('result_key', $nodeType)
            ->first();

        // 3、保存当前流程状态
        $workflowProcessData = [
            'apply_key'   => $tableName,
            'node_id'     => $nodeProgram->next_node_id,
            'result_name' => $nodeProgram->result_name,
            'status'      => $nodeProgram->result_status,
            'reason'      => $reason,
        ];
        $modelObj->process()->updateOrCreate(
            [
                'apply_id'  => $modelObj->id,
                'apply_key' => $tableName,
            ],
            $workflowProcessData
        );

        // 4、记录流程日志
        $workflowLogData = [
            'apply_key'   => $tableName,
            'node_id'     => $nodeProgram->node_id,
            'result_name' => $nodeProgram->result_name,
            'status'      => $nodeProgram->result_status,
            'reason'      => $reason,
        ];
        $workflowLog = new WorkflowLog($workflowLogData);
        $modelObj->logs()->save($workflowLog);
    }

    /**
     * 修改文章
     *
     * @param  Request  $request
     * @param           $id
     *
     * @return mixed
     */
    public function updateAccident(Request $request, $id)
    {
        $params = $request->all();
        // 删除陕G
        if ($params['license_plate_num']) {
            $params['license_plate_num'] = Str::of($params['license_plate_num'])->replace('陕G', '');
        }
        // UTC时间转化
        if ($params['date']) {
            $params['date'] = date('Y-m-d', strtotime($params['date']));
        }
        // 多文件转化为字符拼接
        if ($params['accident_file']) {
            $accidentFiles = array_column($params['accident_file'], 'file_path');
            $params['accident_file'] = implode(';', $accidentFiles);
        } else {
            $params['accident_file'] = '';
        }
        // 编制案号
        $params['number'] = $this->setAccidentNumber($params['date']);
        $params['user_name'] = $params['driver'];
        $charteredCar = Accident::query()->find($id);

        $result = $charteredCar->update($params);

        // 关联资料详情
        if (! empty($params['detailData'])) {
            $charteredCar->document()->delete();
            foreach ($params['detailData'] as $work) {
                $work['type'] = 'file';
                $file = new AccidentDocument($work);
                $charteredCar->document()->save($file);
            }
        }else{
            $charteredCar->document()->delete();
        }

        // 关联维修详情
        if (! empty($params['maintainData'])) {
            $charteredCar->repair()->delete();
            foreach ($params['maintainData'] as $pay) {
                $family = new AccidentRepair($pay);
                $charteredCar->repair()->save($family);
            }
        }else{
            $charteredCar->repair()->delete();
        }

        // 关联人伤情况
        if (! empty($params['hurtData'])) {
            $charteredCar->injured()->delete();
            foreach ($params['hurtData'] as $pay) {
                $family = new AccidentInjured($pay);
                $charteredCar->injured()->save($family);
            }
        }else{
            $charteredCar->injured()->delete();
        }

        $message = $result ? '添加成功' : '添加失败';

        $this->updateWorkflow($charteredCar, $params['nodeKey'], $params['nodeType'], '');


        return response()->formatJson($result, $message);
    }

    /**
     * 删除事故信息
     *
     * @param  Request  $request
     *
     * @return mixed
     */
    public function destroyAccident(Request $request)
    {
        $charteredCar = Accident::query()->find($request['ids']);
        if ($charteredCar) {
            $result = Accident::where('id', $request['ids'])->delete();
            $charteredCar->document()->delete();
            $charteredCar->repair()->delete();
            $charteredCar->injured()->delete();
        } else {
            $result = false;
        }
        $message = $result ? '删除成功' : '删除失败';

        return response()->formatJson($result, $message);
    }


    /**
     * 审核维修申请
     *
     * @param  Request  $request
     *
     * @return mixed
     */
    public function audit(Request $request)
    {
        $params = $request->input('params');
        $mrApply = Accident::query()->find($params['id']);

        $this->updateWorkflow($mrApply, $params['nodeKey'], $params['nodeType'], $params['reason']);

        $message = $params['nodeType'] === 'pass' || $params['nodeType'] === 'end' ? '审核通过' : '审核不通过';

        return response()->formatJson(['result' => true, 'nodeType' => $params['nodeType']], $message);
    }

    /**
     * 获取驾驶员列表
     *
     * @return mixed
     */
    public function driverPersonnel()
    {
        return response()->formatJson(['result' => Personnel::query()->where('type', 1)->get()]);
    }
}
